package cn.suimg.neo4j.util;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;

/**
 * 计数器进度工具类
 */
public class ProgressUtil implements AutoCloseable{

    /**
     * 计数器
     */
    private final AtomicInteger count = new AtomicInteger(0);

    /**
     * 上一次的计数
     */
    private final AtomicInteger lastCount = new AtomicInteger(0);

    /**
     * 每秒处理速度
     */
    private final AtomicInteger perSecondSpeed = new AtomicInteger(0);

    /**
     * 当前进度0-100
     */
    private final AtomicInteger currentProgress = new AtomicInteger(0);

    /**
     * 用于退出每秒计数
     */
    private final AtomicBoolean isEnd = new AtomicBoolean(false);

    private final Integer total;

    private final String name;

    private final Long delay;
    private final Consumer<String> consumer;

    public static ProgressUtil getInstance(String name, Integer total, Long delay, Consumer<String> consumer){
        return new ProgressUtil(name,total,delay,consumer);
    }

    private ProgressUtil(String name,Integer total, Long delay, Consumer<String> consumer){
        this.name = name;
        this.total = total;
        this.delay = delay;
        this.consumer = consumer;
        perSecondCounter();
        consumerCount();
    }

    /**
     * 计算处理速度和进度
     */
    private void perSecondCounter(){
        ThreadPoolUtil.submit(() -> {
            while (!isEnd.get()){
                int currentCount = count.get();
                perSecondSpeed.set(currentCount - lastCount.get());
                lastCount.set(currentCount);
                currentProgress.set((int)((double) currentCount / total * 100));
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ignored) {}
            }
        });
    }


    private void consumerCount(){
        ThreadPoolUtil.submit(() -> {
            while (!isEnd.get()){
                consumer.accept(toString());
                try {
                    Thread.sleep(delay);
                } catch (InterruptedException ignored) {}
            }
        });
    }

    /**
     * 获取每秒的处理速度
     * @return
     */
    public Integer getPreSecondDealSpeed(){
        return perSecondSpeed.get();
    }

    /**
     * 获取总进度
     * @return
     */
    public Integer getTotalProgress(){
        return currentProgress.get();
    }

    @Override
    public String toString(){
        return String.format("[%s:%d/%d]====PreSecondDealSpeed:%d====TotalProgress:%d%%",name,count.get(),total,getPreSecondDealSpeed(),getTotalProgress());
    }

    /**
     * 每次处理完1条调用该方法计数
     */
    public void count(){
        count.incrementAndGet();
    }

    public void destroy(){
        isEnd.set(true);
    }

    @Override
    public void close() throws Exception {
        destroy();
    }
}
